package me.Adventure;

import me.enums.Directions;
import me.enums.ItemType;
import me.model.AdventureItem;
import me.model.Brick;
import me.model.Hero;
import me.model.Room;
import me.model.Spear;

import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Polygon;

public class Adventure extends BasicGame {

	public final static int SCREEN_WIDTH = 800;
	public final static int SCREEN_HEIGHT = 480;

	public final static float squareHeight = 20.0f;
	public final static float squareWidth = 20.0f;

	private Room room = Room.getInstance();
	private ItemPosition itemsPosition = ItemPosition.getInstance();

	private Image screen = null;
	private Hero hero = null;
	private BrickMap brickMap;

	private final int INIT = 1;

	private Polygon spear;

	public Adventure() {
		super("Adventure 0.02b");
	}

	@Override
	public void init(GameContainer container) throws SlickException {

		brickMap = new BrickMap(INIT);
		room.changeRoom(INIT);
		screen = room.imageRoom(INIT);

		hero = new Hero(380, 460);

		spear = new Spear(ItemType.SPEAR, 400, 400, INIT).poly;

	}

	@Override
	public void update(GameContainer container, int delta) throws SlickException {

		Input input = container.getInput();
		float x = hero.getX();
		float y = hero.getY();
		AdventureItem item;
		Directions dir;

		/* UP */
		if(input.isKeyDown(Input.KEY_UP)) {
			dir = Directions.UP;
			hero.move(dir);

			if(collideWithScenario()) hero.move(invertDirection(dir));

			item = collideWithItem();
			if(item!=null) hero.pickItem(item, dir);

			if(hero.getItem()!=null){
				System.out.println(hero.getItem().getY());
				hero.getItem().setY(y);
			}

		}

		/* DOWN */
		if(input.isKeyDown(Input.KEY_DOWN)) {
			dir = Directions.DOWN;
			hero.move(dir);

			if(collideWithScenario()) hero.move(invertDirection(dir));

			item = collideWithItem();
			if(item!=null) hero.pickItem(item, dir);

			if(hero.getItem()!=null){
				hero.getItem().setY(y);
			}

		}

		/* RIGHT */
		if(input.isKeyDown(Input.KEY_RIGHT)) {
			dir = Directions.RIGHT;
			hero.move(dir);

			if(collideWithScenario()) hero.move(invertDirection(dir));

			item = collideWithItem();
			if(item!=null) hero.pickItem(item, dir);

			if(hero.getItem()!=null){
				ItemPosition.getInstance().placeAdventureItem();
				hero.getItem().setX(x);
			}

		}

		/* LEFT */
		if(input.isKeyDown(Input.KEY_LEFT)){
			dir = Directions.LEFT;
			hero.move(dir);

			if(collideWithScenario()) hero.move(invertDirection(dir));

			item = collideWithItem();
			if(item!=null) hero.pickItem(item, dir);

			if(hero.getItem()!=null){
				hero.getItem().setX(x);
			}
		}

		if (!(warp() < 0)){
			screen = room.imageRoom(room.getScreenCode());
			brickMap = new BrickMap(room.getScreenCode());
		}

	}

	public void render(GameContainer container, Graphics g) throws SlickException {

		g.drawImage(screen, 0, 0);
		g.draw(hero.getSquare());
		g.drawString("x: " + hero.getX(), 700, 5);
		g.drawString("y: " + hero.getY(), 700, 20);
		g.drawString("("+ (hero.getX() / SCREEN_WIDTH) * 100 +")("+ (hero.getY() / SCREEN_HEIGHT) * 100 +")", 600, 40);
		for(AdventureItem ai : ItemPosition.getInstance().getEntities()){
			if(isItemOnScreen(ai)) g.draw(ai.poly);
		}

	}

	public static void main(String[] args) throws SlickException {

		int altura = SCREEN_HEIGHT;
		int largura = SCREEN_WIDTH;

		AppGameContainer app = new AppGameContainer(new Adventure());

		app.setDisplayMode(largura, altura, false);
		app.start();
	}

	private int warp() throws SlickException{

		int exit = -1;
		int exitCode = 0;
		int up = (int) this.hero.getY();
		int down = (int) (this.hero.getY() + this.squareHeight);
		int left = (int) this.hero.getX();
		int right = (int) (this.hero.getX() + this.squareWidth);

		if(up < 0){
			exit = room.getNorth();
			exitCode = 1;
		}

		if(down > SCREEN_HEIGHT){
			exit = room.getSouth();
			exitCode = 2;
		}

		if(left < 0) {
			exit = room.getWest();
			exitCode = 3;
		}

		if(right > SCREEN_WIDTH){
			exit = room.getEast();
			exitCode = 4;
		}

		// saiu da tela
		if(!(exit < 0)){

			float x = 0;
			float y = 0;

			switch(exitCode){

			case 1:{
				x = this.hero.getX();
				y = (SCREEN_HEIGHT - squareHeight);
				break;
			}

			case 2:{
				x = this.hero.getX();
				y = 0;
				break;
			}

			case 3:{
				x = (SCREEN_WIDTH - squareWidth);
				y = this.hero.getY();
				break;
			}

			case 4:{
				x = 0;
				y = this.hero.getY();
				break;
			}
			}

			// set the new room
			room.changeRoom(exitCode);

			// set hero location
			hero.setX(x);
			hero.setY(y);

		}

		return exit;

	}

	public boolean collideWithScenario() throws SlickException {

		for(Brick b : BrickMap.entities){
			if (hero.getSquare().intersects(b.poly)) {
				return true;
			}
		}
		return false;
	}

	public AdventureItem collideWithItem() throws SlickException {

		AdventureItem myItem = null;
		
		for(AdventureItem ai: ItemPosition.getInstance().getEntities()){
			if(hero.getSquare().intersects(ai.poly)){
				myItem = ai;
				break;
			}
		}
				
		return myItem;
	}

	public boolean isItemOnScreen(AdventureItem item){
		return (room.getScreenCode()==item.getScreencode());
	}

	private Directions invertDirection(Directions dir){

		Directions inv = null;

		switch (dir){

		case UP: inv = Directions.DOWN; break;
		case DOWN: inv = Directions.UP; break;
		case LEFT: inv = Directions.RIGHT; break;
		case RIGHT: inv = Directions.LEFT; break;
		}

		return inv;

	}

}